home *** CD-ROM | disk | FTP | other *** search
/ PCMania 30 / PCMania CD30.iso / pcmania / graf30 / tacs / readutil.c < prev    next >
C/C++ Source or Header  |  1988-04-27  |  13KB  |  578 lines

  1. #include <tiff.h>
  2.  
  3. #define LINE_SIZE 320
  4. #define BUFFER_SIZE 512
  5. #define NULL 0
  6. #define BITS_PER_BYTE    8
  7. #define ONE_D_MODIFIED_HUFFMAN    2
  8.  
  9. extern void bigfree();
  10. extern void debug();
  11. extern int sprintf();
  12.  
  13. extern SHORT read_header();
  14. extern SHORT read_tag();
  15. extern SHORT read_dirent();
  16. extern SHORT decompress_block();
  17. extern SHORT decompress_error;
  18.  
  19. extern BOOL access_ifd();
  20.  
  21. extern LONGPTR bigalloc();
  22. extern LONGPTR decblk;        /* decompression block */
  23. extern LONGPTR decblk2;
  24. extern SHORT l_compression;
  25.  
  26. extern LONG lseek();
  27. extern LONG bigRead();
  28.  
  29. /*
  30.  * Declaring a global variable to be "static" causes it to be considered
  31.  * global only within this source file.  Hence, these "statics" will be
  32.  * invisible to any other routines.  This avoids unnecessary name clashes
  33.  * and keeps these routines and variables out of the load map.
  34.  */
  35.  
  36. /* static routines */
  37. static LONG get_buffer();
  38.  
  39. static BOOL readimg_init();
  40. static BOOL read_strip_tables();
  41. static BOOL read_dirct_valu();
  42.  
  43. /* static global variables */
  44. static SHORT current_handle = (SHORT)(-1);
  45. SHORT readimg_handle = (SHORT)(-1);
  46. static SHORT image_width;
  47. static SHORT compression_type = 0;
  48. static SHORT residual = 0;
  49.  
  50. static BOOL decompress = FALSE;
  51. static BOOL initialize_read = FALSE;
  52. static BOOL one_at_a_time = FALSE;
  53.  
  54. static char *dc_ptr = NULL;
  55. static char temp_line_buff[LINE_SIZE];
  56. static char decomp_buffer[BUFFER_SIZE];
  57.  
  58. static LONG rows_per_strip;
  59. static LONG bytes_per_line;
  60. static LONG start_strip;
  61. static LONG num_strips;
  62. static LONG prev_start_strip = -1L;
  63. static LONG prev_num_strips = -1L;
  64. static LONG strip_index;
  65. static LONG current_line;
  66. static LONG current_byte;
  67. static LONG decomp_bytes_left = 0L;
  68. static LONG num_sb_count;
  69. static LONG off_sb_count;
  70. static LONG num_str_off;
  71. static LONG off_str_off;
  72. static LONG max_strip_size;
  73. static LONG file_position = -1L;
  74. static LONG next_line_to_read = -1L;
  75. static LONG save_file_position = -1L;
  76. static LONG number_of_bytes;
  77. static SHORT samp_per_pix;
  78. static SHORT bits_per_samp;
  79.  
  80. /*
  81.  * These globals are accessible by any routine.
  82.  */
  83. extern LONG far *so_table;
  84. extern LONG far *sbc_table;
  85.  
  86. LONG _TIFF_image_bytes_read;
  87. LONG _TIFF_image_lines_read;
  88. #ifdef DEBUG
  89. BOOL _TIFF_debug_flag = TRUE;
  90. #else
  91. BOOL _TIFF_debug_flag = FALSE;
  92. #endif /* DEBUG */
  93. LONG bytes_processed = 0;
  94.  
  95. #ifdef NOWINDOWS
  96. /*
  97.  * The flag for one-byte-at-a-time versus buffered mode is a static, so
  98.  * that no routine that is linked in can access it.  It is set or cleared
  99.  * by means of this SetBufferedMode() routine.    When debugging, compile
  100.  * with the NOWINDOWS flag defined if you want to be able to use this
  101.  * routine to alter this mode.    Without NOWINDOWS, this routine never
  102.  * gets compiled, and so there'd be no way to alter the buffering mode
  103.  * from the default value (default == buffered) short of using a debugger
  104.  * or patching the code.
  105.  */
  106. void
  107. SetBufferedMode(buffered)
  108. BOOL buffered;
  109. {
  110.     if(buffered)
  111.     {
  112.         one_at_a_time = FALSE;
  113.     }
  114.     else
  115.     {
  116.         one_at_a_time = TRUE;
  117.     }
  118. }
  119. #endif /* NOWINDOWS */
  120.  
  121. /* return position of top of IFD list (or zero if error) */
  122. LONG
  123. far get_1st_ifd(fhandle)
  124. SHORT fhandle;
  125. {
  126.  
  127.     static TIFF_HEADER curr_header;
  128.  
  129.     if(fhandle != current_handle)
  130.     {
  131.         current_handle = fhandle;
  132.         if(read_header(fhandle, (TIFF_HEADER far *)&curr_header) !=
  133.           TIFF_HEADER_SIZE)
  134.         {
  135.             return(0L);
  136.         }
  137.     }
  138.     return(curr_header.dir_offset);
  139. }
  140.  
  141. /* clean up image reading environment */
  142. SHORT
  143. close_read(fhandle)
  144. SHORT fhandle;
  145. {
  146.     /* reinitialize handles */
  147.     if(current_handle == fhandle)
  148.     {
  149.         current_handle = (SHORT)(-1);
  150.     }
  151.     if(readimg_handle == fhandle)
  152.     {
  153.         readimg_handle = (SHORT)(-1);
  154.     }
  155.  
  156.     /* free buffers, reinitialize pointers and sizes */
  157.     bigfree(sbc_table);
  158.     bigfree(so_table);
  159.     if(l_compression == ONE_D_MODIFIED_HUFFMAN) {
  160.         bigfree(decblk);
  161.         bigfree(decblk2);
  162.     }
  163.     sbc_table = 0L;
  164.     so_table = 0L;
  165.     file_position = -1L;
  166.     return(1);
  167. }
  168.  
  169.  
  170. /* read appropriate tags and such */
  171. static BOOL
  172. readimg_init(fhandle, fdtype)
  173. SHORT fhandle;
  174. SHORT fdtype;
  175. {
  176.     TIFF_DIR_ENTRY dirent;
  177.  
  178.     readimg_handle = fhandle;
  179.     bigfree(so_table);
  180.     bigfree(sbc_table);
  181.     start_strip = -1L;
  182.     prev_start_strip = -1L;
  183.     num_strips = 0L;
  184.     prev_num_strips = -1L;
  185.     so_table = 0L;
  186.     sbc_table = 0L;
  187.     decomp_bytes_left = 0L;
  188.     dc_ptr = NULL;
  189.     num_sb_count = 0L;
  190.     off_sb_count = 0L;
  191.     num_str_off = 0L;
  192.     off_str_off = 0L;
  193.     max_strip_size = 0L;
  194.     compression_type = 0;
  195.     decompress = FALSE;
  196.     next_line_to_read = -1L;
  197.     save_file_position = -1L;
  198.  
  199.     if(!read_tag(fhandle, fdtype, IMAGE_WIDTH_TAG,
  200.       (LONGPTR)&image_width, (SHORT)SHORT_SIZE))
  201.     {
  202.         return(TRUE);
  203.     }
  204.  
  205.     /* bits per sample */
  206.     if(!read_tag(fhandle, fdtype, BITS_PER_SAMPLE_TAG,
  207.       (LONGPTR)&bits_per_samp, (SHORT)SHORT_SIZE))
  208.  
  209.     {
  210.         bits_per_samp = 1;
  211.     }
  212.  
  213.     /* samples_per_pixel */
  214.     if(!read_tag(fhandle, fdtype, SAMPLES_PER_PIXEL_TAG,
  215.       (LONGPTR)&samp_per_pix, (SHORT)SHORT_SIZE))
  216.     {
  217.         samp_per_pix = 1;
  218.     }
  219.  
  220.     /* rows per strip */
  221.     if(!read_tag(fhandle, fdtype, ROWS_PER_STRIP_TAG,
  222.       (LONGPTR)&rows_per_strip, (SHORT)LONG_SIZE))
  223.     {
  224.         rows_per_strip = 0L;
  225.     }
  226.  
  227.     /* compression */
  228.     if(!read_tag(fhandle, fdtype, COMPRESSION_TAG,
  229.       (LONGPTR)&compression_type, (SHORT)SHORT_SIZE))
  230.     {
  231.         decompress = FALSE;
  232.     }
  233.     else
  234.     {
  235.         /*
  236.          * Currently (9/7/86), the only compression this
  237.          * routine can handle is the 1-Dimensional Modified
  238.          * Huffman run length encoding technique.
  239.          */
  240.         switch(compression_type)
  241.         {
  242.         case ONE_D_MOD_HUFFMAN:
  243.             decompress = TRUE;
  244.             break;
  245.  
  246.         default:
  247.             decompress = FALSE;
  248.             compression_type = 0;
  249.         }
  250.     }
  251.  
  252.     /* strip offsets */
  253.     if(!read_dirent(fhandle, fdtype, STRIP_OFFSETS_TAG,
  254.       (TIFF_DIR_ENTRY far *)&dirent))
  255.     {
  256.         return(TRUE);
  257.     }
  258.     num_str_off = dirent.length;
  259.     off_str_off = dirent.value_offset;
  260.  
  261.     /* strip byte counts */
  262.     if(!read_dirent(fhandle, fdtype, STRIP_BYTE_COUNTS_TAG,
  263.       (TIFF_DIR_ENTRY far *)&dirent))
  264.     {
  265.         return(TRUE);
  266.     }
  267.     num_sb_count = dirent.length;
  268.     off_sb_count = dirent.value_offset;
  269.  
  270. debug("    # of strip offsets = %lu, 1st strip offset at %lu\n",
  271.  num_str_off, off_str_off);
  272. debug("    # of strip byte counts = %lu, 1st strip byte count at %lu\n",
  273.  num_sb_count, off_sb_count);
  274.     return(FALSE);
  275. }
  276.  
  277. /* read the strip offsets and strip bytes counts tables */
  278. static BOOL
  279. read_strip_tables(fhandle)
  280. SHORT fhandle;
  281. {
  282.     LONG n;
  283.     LONG seek_pos;
  284.     LONG read_len;
  285.  
  286.     prev_start_strip = start_strip;
  287.     prev_num_strips = num_strips;
  288.  
  289.     bigfree(so_table);
  290.     bigfree(sbc_table);
  291.     so_table = 0L;
  292.     sbc_table = 0L;
  293.  
  294.     /* allocate space for strip offsets table */
  295.     so_table = (LONG far *)bigalloc(num_strips * (LONG)LONG_SIZE);
  296.     if(!so_table)
  297.     {
  298.         readimg_handle = -1;
  299.         return(TRUE);
  300.     }
  301.  
  302.     /* allocate space for strip byte counts table */
  303.     sbc_table = (LONG far *)bigalloc(num_strips *
  304.       (LONG)LONG_SIZE);
  305.     if(!sbc_table)
  306.     {
  307.         readimg_handle = -1;
  308.         bigfree(so_table);
  309.         so_table = 0L;
  310.         return(TRUE);
  311.     }
  312.  
  313.     /* read appropriate portion of strip offsets table */
  314.     seek_pos = off_str_off + start_strip * (LONG)LONG_SIZE;
  315.     if(lseek(fhandle, seek_pos, 0) != seek_pos)
  316.     {
  317.         readimg_handle = -1;
  318.         file_position = -1L;
  319.         bigfree(sbc_table);
  320.         bigfree(so_table);
  321.         so_table = 0L;
  322.         sbc_table = 0L;
  323.         return(TRUE);
  324.     }
  325.     read_len = num_strips * (LONG)LONG_SIZE;
  326.     if(bigRead(fhandle, so_table, read_len) != read_len)
  327.     {
  328.         readimg_handle = -1;
  329.         file_position = -1L;
  330.         bigfree(sbc_table);
  331.         bigfree(so_table);
  332.         so_table = 0L;
  333.         sbc_table = 0L;
  334.         return(TRUE);
  335.     }
  336.  
  337.     /* read appropriate portion of strip byte counts table */
  338.     seek_pos = off_sb_count + start_strip * (LONG)LONG_SIZE;
  339.     if(lseek(fhandle, seek_pos, 0) != seek_pos)
  340.     {
  341.         readimg_handle = -1;
  342.         file_position = -1L;
  343.         bigfree(sbc_table);
  344.         bigfree(so_table);
  345.         so_table = 0L;
  346.         sbc_table = 0L;
  347.         return(TRUE);
  348.     }
  349.     read_len = num_strips * (LONG)LONG_SIZE;
  350.     if(bigRead(fhandle, sbc_table, read_len) != read_len)
  351.     {
  352.         readimg_handle = -1;
  353.         file_position = -1L;
  354.         bigfree(sbc_table);
  355.         bigfree(so_table);
  356.         so_table = 0L;
  357.         sbc_table = 0L;
  358.         return(TRUE);
  359.     }
  360.  
  361.     /* go through table of strip byte counts and get maximum */
  362.     max_strip_size = 0L;
  363.     for(n = 0; n < num_strips; ++n)
  364.     {
  365. debug("    strip %4ld: offset %lu, byte count %lu\n", n, so_table[n],
  366.  sbc_table[n]);
  367.         if(max_strip_size < sbc_table[n])
  368.         {
  369.             max_strip_size = sbc_table[n];
  370.         }
  371.     }
  372.  
  373.     return(FALSE);
  374. }
  375.  
  376. /* get a buffer from the file */
  377. static LONG
  378. get_buffer(data_buffer, size)
  379. LONGPTR data_buffer;
  380. LONG size;
  381. {
  382.     LONG table_offset = strip_index - start_strip;
  383.     LONG bytes_per_strip = sbc_table[table_offset];
  384.     LONG seek_pos;
  385.     LONG read_len;
  386.     LONG len;
  387.  
  388.     /* see if we need to go to the next strip */
  389.     if(current_byte >= bytes_per_strip)
  390.     {
  391.         /* we're done if strip table is exhausted */
  392.         if(++table_offset >= num_strips)
  393.         {
  394.             return(-1L);
  395.         }
  396.         bytes_per_strip = sbc_table[table_offset];
  397.  
  398.         /* we're done if it's an empty strip */
  399.         if(bytes_per_strip < 1)
  400.         {
  401.             return(-1L);
  402.         }
  403.         strip_index = start_strip + table_offset;
  404.         current_byte = 0L;
  405.         residual = 0;
  406.     }
  407.  
  408.     /*
  409.      * Seek to the appropriate position.  Do this each time in case
  410.      * the caller has seeked elsewhere in the interim.
  411.      */
  412.     seek_pos = so_table[table_offset] + current_byte;
  413.     if((file_position = lseek(readimg_handle, seek_pos, 0)) != seek_pos)
  414.     {
  415.         file_position = -1L;
  416.         return(-1L);
  417.     }
  418.  
  419.     /* figure out how much to read and then do it */
  420.     read_len = size;
  421.     if(read_len + current_byte > bytes_per_strip)
  422.     {
  423.         read_len = bytes_per_strip - current_byte;
  424.     }
  425.     if(read_len <= 0)
  426.     {
  427.         return(-1L);
  428.     }
  429.     len = bigRead(readimg_handle, data_buffer, read_len);
  430.     if(len >= 0)
  431.     {
  432.         current_byte += len;
  433.     }
  434.     return(len);
  435. }
  436.  
  437. /*
  438.  * This module is to read the stripoffset and stripbytecount values
  439.  * when rows per strip is equal to the image length, 1/12/87
  440.  */
  441.  
  442. static    BOOL
  443. read_dirct_valu(fhandle)
  444. SHORT fhandle;
  445. {
  446.  
  447.     LONG    n;
  448.     prev_start_strip = start_strip;
  449.     prev_num_strips = num_strips;
  450.  
  451.     bigfree(so_table);
  452.     bigfree(sbc_table);
  453.     so_table = 0L;
  454.     sbc_table = 0L;
  455.  
  456.     /* allocate space for strip offsets table */
  457.     so_table = (LONG far *)bigalloc(num_strips * (LONG)LONG_SIZE);
  458.     if(!so_table)
  459.     {
  460.         readimg_handle = -1;
  461.         return(TRUE);
  462.     }
  463.  
  464.     /* allocate space for strip byte counts table */
  465.     sbc_table = (LONG far *)bigalloc(num_strips *
  466.       (LONG)LONG_SIZE);
  467.     if(!sbc_table)
  468.     {
  469.         readimg_handle = -1;
  470.         bigfree(so_table);
  471.         so_table = 0L;
  472.         return(TRUE);
  473.     }
  474.  
  475.     *so_table = off_str_off;
  476.     *sbc_table = off_sb_count;
  477.  
  478.     max_strip_size = 0L;
  479.     for(n = 0; n < num_strips; ++n)
  480.     {
  481. debug("    strip %4ld: offset %lu, byte count %lu\n", n, so_table[n],
  482.  sbc_table[n]);
  483.         if(max_strip_size < sbc_table[n])
  484.         {
  485.             max_strip_size = sbc_table[n];
  486.         }
  487.     }
  488.  
  489.     return(FALSE);
  490.  
  491. }
  492.  
  493. /*
  494.  * General get-byte routine.  It's needed for decompression, so I
  495.  * might as well use it for uncompressed data as well.
  496.  */
  497. SHORT
  498. GetDecompByte()
  499. {
  500.     SHORT ch;
  501.     LONG table_offset = strip_index - start_strip;
  502.     LONG bytes_per_strip = sbc_table[table_offset];
  503.     LONG seek_pos;
  504.  
  505. #ifdef NOWINDOWS
  506.     if(one_at_a_time)
  507.     {
  508.         if(initialize_read)
  509.         {
  510.             current_byte = bytes_per_strip;
  511.             --table_offset;
  512.             initialize_read = FALSE;
  513.         }
  514.         /* see if we need to go to the next strip */
  515.         if(current_byte >= bytes_per_strip)
  516.         {
  517.             /* we're done if strip table is exhausted */
  518.             if(++table_offset >= num_strips)
  519.             {
  520.                 return((SHORT)0xffff);
  521.             }
  522.             bytes_per_strip = sbc_table[table_offset];
  523.  
  524.             /* we're done if it's an empty strip */
  525.             if(bytes_per_strip < 1L)
  526.             {
  527.                 return((SHORT)0xffff);
  528.             }
  529.             strip_index = start_strip + table_offset;
  530.             current_byte = 0L;
  531.             residual = 0;
  532.             seek_pos = so_table[table_offset];
  533.             if((file_position = lseek(readimg_handle, seek_pos,
  534.               0)) != seek_pos)
  535.             {
  536.                 file_position = -1L;
  537.                 return((SHORT)0xffff);
  538.             }
  539.         }
  540.  
  541.         if(bigRead(readimg_handle, (LONGPTR)&ch, 1L) < 1L)
  542.         {
  543.             return((SHORT)0xffff);
  544.         }
  545.         ++current_byte;
  546.         ++number_of_bytes;
  547.         file_position = lseek(readimg_handle, 0L, 1);
  548.         return(ch & 0xff);
  549.     }
  550.     else
  551.     {
  552. #endif /* NOWINDOWS */
  553.         /* read next buffer if necessary */
  554.         if(decomp_bytes_left <= 0 || !dc_ptr)
  555.         {
  556.             decomp_bytes_left =
  557.               get_buffer((LONGPTR)decomp_buffer,
  558.               (LONG)BUFFER_SIZE);
  559.  
  560.             /* if error or eof, return 0xffff */
  561.             if(decomp_bytes_left <= 0)
  562.             {
  563.                 return((SHORT)0xffff);
  564.             }
  565.             dc_ptr = decomp_buffer;
  566.         }
  567.  
  568.         /* return next character */
  569.         --decomp_bytes_left;
  570.         ++file_position;
  571.         ++number_of_bytes;
  572.         ch = (SHORT)(*dc_ptr++);
  573.         return(ch & 0xff);
  574. #ifdef NOWINDOWS
  575.     }
  576. #endif /* NOWINDOWS */
  577. }
  578.